/**
 * Created with CLion.
 * Description:
 * User: loong
 * Date: 2024/3/8
 * Time: 22:23
 */

#ifndef CES_PLUGINPROPERTY_H
#define CES_PLUGINPROPERTY_H
#include "IContext.h"
#include "IPlugin.h"
#include <QtCore>

namespace CES {
    namespace Core {
        class PluginManager;
    }

    namespace Internal {
        struct PluginDepend {
        public:
            enum DependType {
                Required,
                Optional
            };

            QString name_ = "";
            QString version_ = "";
            DependType type_ = Required;

            bool operator==(const PluginDepend &other) const;
        };

        using PluginDependsSPtr = std::shared_ptr<PluginDepend>;
        using PluginDependsVec = std::vector<PluginDependsSPtr>;

        struct PluginSpec {
            QString name_ = "";
            QString version_ = "";
            QString vendor_ = "";
            QString description_ = "";
            QString category_ = "";
            PluginDependsVec depends_;

            static const QRegularExpression versionRegExp_;

            static bool IsValidVersion(const QString &_version);

            static int VersionCompare(const QString &_version1, const QString &_version2);
        };

        using PluginSpecSPtr = std::shared_ptr<PluginSpec>;

        class PluginProperty;
        using PluginPropertySPtr = std::shared_ptr<PluginProperty>;

        class PluginProperty : public QObject {
            Q_OBJECT

        public:
            friend class PluginManager;

            static PluginPropertySPtr ReadFile(const QString &_path);

            bool Provides(const QString &_pluginName, const QString &_pluginVersion) const;

            bool ResolveDepends(const QVector<PluginPropertySPtr> &_specs);

            bool LoadLibrary();

            bool InitPlugin(const Core::IContextSPtr &_content);

            bool StartPlugin();

            bool StopPlugin();

            bool UnInitPlugin();

        private:
            static PluginPropertySPtr ReadMetaData(const QJsonObject &pluginMetaData);

        private:
            //            PluginState                 pluginState_;
            PluginSpecSPtr pluginSpec_;
            bool hasError = false;

            QString errorString = "";
            QVector<PluginPropertySPtr> pluginDepends_;
            QString pluginFilePath_ = "";
            Core::IPluginSPtr pluginSPtr_ = nullptr;

            static QPluginLoader pluginLoader;
        };
    } // namespace Internal
} // namespace CES

#endif//CES_PLUGINPROPERTY_H
